﻿using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;

namespace SE.PO.CInterface.Web.Clients;

public abstract class CurdClientBase<TKey, TDto, TCreateOrUpdate> : ClientBase
{
    protected CurdClientBase(IHttpClientFactory clientFactory, IConfiguration configuration) : base(clientFactory,
        configuration)
    {
    }

    public async Task<PageData<TDto>?> GetPage(string sorting, int? skipCount, int? maxResultCount)
    {
        try
        {
            bool isFirst = true;
            var filter = new StringBuilder();
            if (!string.IsNullOrWhiteSpace(sorting))
            {
                filter.Append($"?Sorting={sorting}");
                isFirst = false;
            }

            if (skipCount != null)
            {
                filter.Append(isFirst ? $"?SkipCount={skipCount}" : $"&SkipCount={skipCount}");
                isFirst = false;
            }

            if (maxResultCount != null)
            {
                filter.Append(isFirst ? $"?MaxResultCount={maxResultCount}" : $"&MaxResultCount={maxResultCount}");
            }

            var client = ClientFactory.CreateClient();
            var request = new HttpRequestMessage
            {
                Method = HttpMethod.Get,
                RequestUri =
                    new Uri($"{BaseUrl}/api/app/{GetRoute()}{filter}"),
            };
            using var response = await client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            var body = await response.Content.ReadAsStringAsync();
            Console.WriteLine(body);
            return JsonConvert.DeserializeObject<PageData<TDto>>(body);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }

    public async Task Delete(TKey id)
    {
        var client = ClientFactory.CreateClient();
        var request = new HttpRequestMessage
        {
            Method = HttpMethod.Delete,
            RequestUri = new Uri($"{BaseUrl}/api/app/{GetRoute()}/{id}"),
        };
        using var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        var body = await response.Content.ReadAsStringAsync();
        Console.WriteLine(body);
    }

    private async Task DeleteManyByBatchAsync(string ids)
    {
        var client = ClientFactory.CreateClient();
        var request = new HttpRequestMessage
        {
            Method = HttpMethod.Delete,
            RequestUri = new Uri($"{BaseUrl}/api/app/{GetRoute()}/many{ids}"),
        };
        using var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        var body = await response.Content.ReadAsStringAsync();
        Console.WriteLine(body);
    }

    public async Task DeleteManyAsync(IEnumerable<TKey> ids)
    {
        var sbIds = new StringBuilder();
        var enumerable = ids as TKey[] ?? ids.ToArray();
        if (enumerable.Any())
        {
            foreach (var t in enumerable)
            {
                if (string.IsNullOrWhiteSpace(sbIds.ToString()))
                {
                    sbIds.Append($"?ids={t}");
                }
                else
                {
                    sbIds.Append($"&ids={t}");
                }

                if (sbIds.Length > 1800)
                {
                    //分批
                    await DeleteManyByBatchAsync(sbIds.ToString());
                    sbIds.Clear();
                }
            }

            if (!string.IsNullOrWhiteSpace(sbIds.ToString()))
            {
                //剩余
                await DeleteManyByBatchAsync(sbIds.ToString());
            }
        }
    }

    public async Task<bool> DeleteAllAsync()
    {
        var client = ClientFactory.CreateClient();
        var request = new HttpRequestMessage
        {
            Method = HttpMethod.Delete,
            RequestUri = new Uri($"{BaseUrl}/api/app/{GetRoute()}/all"),
        };
        using var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        var body = await response.Content.ReadAsStringAsync();
        Console.WriteLine(body);
        return bool.Parse(body);
    }

    public async Task<TDto?> Get(TKey id)
    {
        var client = ClientFactory.CreateClient();
        var request = new HttpRequestMessage
        {
            Method = HttpMethod.Get,
            RequestUri = new Uri($"{BaseUrl}/api/app/{GetRoute()}/{{id}}"),
        };
        using var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        var body = await response.Content.ReadAsStringAsync();
        Console.WriteLine(body);
        return JsonConvert.DeserializeObject<TDto>(body);
    }

    public async Task<TDto?> Post(TCreateOrUpdate t)
    {
        try
        {
            var client = ClientFactory.CreateClient();
            var request = new HttpRequestMessage
            {
                Method = HttpMethod.Post,
                RequestUri = new Uri($"{BaseUrl}/api/app/{GetRoute()}"),
                Content = new StringContent(JsonConvert.SerializeObject(t))
                {
                    Headers =
                    {
                        ContentType = new MediaTypeHeaderValue("application/json")
                    }
                }
            };
            using var response = await client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            var body = await response.Content.ReadAsStringAsync();
            Console.WriteLine(body);
            return JsonConvert.DeserializeObject<TDto>(body);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }

    public async Task<TDto?> Put(TKey id, TCreateOrUpdate t)
    {
        var client = ClientFactory.CreateClient();
        var request = new HttpRequestMessage
        {
            Method = HttpMethod.Put,
            RequestUri = new Uri($"{BaseUrl}/api/app/{GetRoute()}/{id}"),
            Content = new StringContent(JsonConvert.SerializeObject(t))
            {
                Headers =
                {
                    ContentType = new MediaTypeHeaderValue("application/json")
                }
            }
        };
        using var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        var body = await response.Content.ReadAsStringAsync();
        Console.WriteLine(body);
        return JsonConvert.DeserializeObject<TDto>(body);
    }
}